home *** CD-ROM | disk | FTP | other *** search
/ Network PC / Network PC.iso / amiga utilities / graphics / display / mpega / src / aiff.c next >
Encoding:
C/C++ Source or Header  |  1997-11-20  |  8.0 KB  |  278 lines

  1. /*------------------------------------------------------------------------------
  2.  
  3.     File    :    AIFF.c
  4.  
  5.     Author  :    Stéphane TAVENARD
  6.  
  7.     $VER:   AIFF.c  1.0  (23/06/1995)
  8.  
  9.     (C) Copyright 1995-1995 Stéphane TAVENARD
  10.     All Rights Reserved
  11.  
  12.     #Rev|   Date   |              Comment
  13.     ----|----------|--------------------------------------------------------
  14.     0    |05/06/1995| Initial revision from file common.c of
  15.     |       | MPEG/audio software simulation group          ST
  16.     1    |23/06/1995| Aminet release                      ST
  17.  
  18.     ------------------------------------------------------------------------
  19.  
  20.     AIFF utilities
  21.  
  22. ------------------------------------------------------------------------------*/
  23.  
  24. #include <stdio.h>
  25. #include <stdlib.h>
  26. #include <ctype.h>
  27. #include "AIFF.h"
  28.  
  29. #define     BITS_IN_A_BYTE        8
  30.  
  31.  
  32. /****************************************************************************
  33. *
  34. *  Routines to convert between the Apple SANE extended floating point format
  35. *  and the IEEE double precision floating point format.  These routines are
  36. *  called from within the Audio Interchange File Format (AIFF) routines.
  37. *
  38. *****************************************************************************/
  39.  
  40. /*
  41. *** Apple's 80-bit SANE extended has the following format:
  42.  
  43.  1     15     1          63
  44. +-+-------------+-+-----------------------------+
  45. |s|      e    |i|           f        |
  46. +-+-------------+-+-----------------------------+
  47.   msb         lsb   msb                 lsb
  48.  
  49. The value v of the number is determined by these fields as follows:
  50. If 0 <= e < 32767,        then v = (-1)^s * 2^(e-16383) * (i.f).
  51. If e == 32767 and f == 0,    then v = (-1)^s * (infinity), regardless of i.
  52. If e == 32767 and f != 0,    then v is a NaN, regardless of i.
  53.  
  54. *** IEEE Draft Standard 754 Double Precision has the following format:
  55.  
  56. MSB
  57. +-+---------+-----------------------------+
  58. |1| 11 Bits |        52 Bits       |
  59. +-+---------+-----------------------------+
  60.  ^     ^        ^
  61.  |     |        |
  62.  Sign  Exponent     Mantissa
  63. */
  64.  
  65. /*****************************************************************************
  66. *
  67. *  double_to_extended()
  68. *
  69. *  Purpose:    Convert from IEEE double precision format to SANE extended
  70. *        format.
  71. *
  72. *  Passed:    Pointer to the double precision number and a pointer to what
  73. *        will hold the Apple SANE extended format value.
  74. *
  75. *  Outputs:    The SANE extended format pointer will be filled with the
  76. *        converted value.
  77. *
  78. *  Returned:    Nothing.
  79. *
  80. *****************************************************************************/
  81.  
  82. static void double_to_extended( double *pd, char ps[ 10 ] )
  83. {
  84.    register unsigned long  top2bits;
  85.  
  86.    register unsigned short *ps2;
  87.    register IEEE_DBL       *p_dbl;
  88.    register SANE_EXT       *p_ext;
  89.  
  90.    p_dbl = (IEEE_DBL *) pd;
  91.    p_ext = (SANE_EXT *) ps;
  92.    top2bits = p_dbl->hi & 0xc0000000;
  93.    p_ext->l1 = ((p_dbl->hi >> 4) & 0x3ff0000) | top2bits;
  94.    p_ext->l1 |= ((p_dbl->hi >> 5) & 0x7fff) | 0x8000;
  95.    p_ext->l2 = (p_dbl->hi << 27) & 0xf8000000;
  96.    p_ext->l2 |= ((p_dbl->lo >> 5) & 0x07ffffff);
  97.    ps2 = (unsigned short *) & (p_dbl->lo);
  98.    ps2++;
  99.    p_ext->s1 = (*ps2 << 11) & 0xf800;
  100. }
  101.  
  102. /*****************************************************************************
  103. *
  104. *  extended_to_double()
  105. *
  106. *  Purpose:    Convert from SANE extended format to IEEE double precision
  107. *        format.
  108. *
  109. *  Passed:    Pointer to the Apple SANE extended format value and a pointer
  110. *        to what will hold the the IEEE double precision number.
  111. *
  112. *  Outputs:    The IEEE double precision format pointer will be filled with
  113. *        the converted value.
  114. *
  115. *  Returned:    Nothing.
  116. *
  117. *****************************************************************************/
  118.  
  119. static void extended_to_double( char ps[ 10 ], double *pd )
  120. {
  121.    register unsigned long  top2bits;
  122.  
  123.    register IEEE_DBL       *p_dbl;
  124.    register SANE_EXT       *p_ext;
  125.  
  126.    p_dbl = (IEEE_DBL *) pd;
  127.    p_ext = (SANE_EXT *) ps;
  128.    top2bits = p_ext->l1 & 0xc0000000;
  129.    p_dbl->hi = ((p_ext->l1 << 4) & 0x3ff00000) | top2bits;
  130.    p_dbl->hi |= (p_ext->l1 << 5) & 0xffff0;
  131.    p_dbl->hi |= (p_ext->l2 >> 27) & 0x1f;
  132.    p_dbl->lo = (p_ext->l2 << 5) & 0xffffffe0;
  133.    p_dbl->lo |= (unsigned long) ((p_ext->s1 >> 11) & 0x1f);
  134. }
  135.  
  136. /*****************************************************************************
  137. *
  138. *  Read Audio Interchange File Format (AIFF) headers.
  139. *
  140. *****************************************************************************/
  141.  
  142. int AIFF_read_headers( FILE *file_ptr, IFF_AIFF *aiff_ptr )
  143. {
  144.    register long   seek_offset;
  145.    register long   sound_position;
  146.  
  147.    ChunkHeader       Header;
  148.    Chunk       FormChunk;
  149.    CommonChunk       CommChunk;
  150.    SoundDataChunk  SndDChunk;
  151.  
  152.    if( fseek( file_ptr, 0, SEEK_SET ) != 0 ) return -1;
  153.  
  154.    if( fread( &FormChunk, sizeof(Chunk), 1, file_ptr ) != 1 ) return -1;
  155.  
  156.    if( (FormChunk.ckID != IFF_ID_FORM) ||
  157.        (FormChunk.formType != IFF_ID_AIFF) ) return -1;
  158.  
  159.    /*
  160.     * chunks need not be in any particular order
  161.     */
  162.  
  163.    while( fread( &Header, sizeof(ChunkHeader), 1, file_ptr ) == 1 ) {
  164.  
  165.       if( Header.ckID == IFF_ID_COMM ) {
  166.      /*
  167.       * read comm chunk
  168.       */
  169.      if( fread( &CommChunk.numChannels,
  170.             sizeof(CommonChunk) - sizeof(ChunkHeader),
  171.             1, file_ptr ) != 1 )
  172.         return -1;
  173.  
  174.      extended_to_double( CommChunk.sampleRate, &aiff_ptr->sampleRate);
  175.      aiff_ptr->numChannels = CommChunk.numChannels;
  176.      aiff_ptr->numSampleFrames = CommChunk.numSampleFrames;
  177.      aiff_ptr->sampleSize = CommChunk.sampleSize;
  178.  
  179.       }
  180.       else if( Header.ckID == IFF_ID_SSND ) {
  181.      /*
  182.       * read ssnd chunk
  183.       */
  184.      if( fread( &SndDChunk.offset,
  185.             sizeof(SoundDataChunk) - sizeof(ChunkHeader),
  186.             1, file_ptr ) != 1 )
  187.         return -1;
  188.  
  189.      aiff_ptr->blkAlgn.offset = SndDChunk.offset;
  190.      aiff_ptr->blkAlgn.blockSize = SndDChunk.blockSize;
  191.      aiff_ptr->sampleType = *(unsigned long *)Header.ckID;
  192.  
  193.      /*
  194.       * record position of sound data
  195.       */
  196.      sound_position = ftell(file_ptr);
  197.  
  198.      /*
  199.       * skip over sound data to look at remaining chunks
  200.       */
  201.      seek_offset = Header.ckSize - sizeof(SoundDataChunk) + sizeof(ChunkHeader);
  202.  
  203.      if( fseek( file_ptr, seek_offset, SEEK_CUR ) != 0 ) return -1;
  204.  
  205.       } else {
  206.      /*
  207.       * skip unknown chunk
  208.       */
  209.      seek_offset = Header.ckSize;
  210.  
  211.      if( fseek( file_ptr, seek_offset, SEEK_CUR ) != 0 ) return -1;
  212.       }
  213.    }
  214.  
  215.    return sound_position ;
  216. }
  217.  
  218. /*****************************************************************************
  219. *
  220. *  Seek past some Audio Interchange File Format (AIFF) headers to sound data.
  221. *
  222. *****************************************************************************/
  223.  
  224. int AIFF_seek_to_sound_data( FILE *file_ptr )
  225. {
  226.    if( fwrite( NULL,
  227.            sizeof(Chunk) + sizeof(CommonChunk) + sizeof(SoundDataChunk),
  228.            1, file_ptr ) != 1) return -1;
  229.    return 0;
  230. }
  231.  
  232. /*******************************************************************************
  233. *
  234. *  Write Audio Interchange File Format (AIFF) headers.
  235. *
  236. *******************************************************************************/
  237.  
  238. int AIFF_write_headers( FILE *file_ptr, IFF_AIFF *aiff_ptr )
  239. {
  240.    Chunk       FormChunk;
  241.    CommonChunk       CommChunk;
  242.    SoundDataChunk  SndDChunk;
  243.  
  244.    FormChunk.ckID     = IFF_ID_FORM;
  245.    FormChunk.formType = IFF_ID_AIFF;
  246.    CommChunk.ckID     = IFF_ID_COMM;
  247.  
  248.    double_to_extended( &aiff_ptr->sampleRate, CommChunk.sampleRate );
  249.  
  250.    CommChunk.numChannels      = aiff_ptr->numChannels;
  251.    CommChunk.numSampleFrames  = aiff_ptr->numSampleFrames;
  252.    CommChunk.sampleSize       = aiff_ptr->sampleSize;
  253.    SndDChunk.offset          = aiff_ptr->blkAlgn.offset;
  254.    SndDChunk.blockSize          = aiff_ptr->blkAlgn.blockSize;
  255.    SndDChunk.ckID          = aiff_ptr->sampleType;
  256.  
  257.    CommChunk.ckSize = sizeof(CommonChunk) - sizeof(ChunkHeader);
  258.  
  259.    SndDChunk.ckSize = sizeof(SoundDataChunk) - sizeof(ChunkHeader) +
  260.       (CommChunk.sampleSize + BITS_IN_A_BYTE - 1) / BITS_IN_A_BYTE *
  261.       CommChunk.numChannels * CommChunk.numSampleFrames;
  262.  
  263.    FormChunk.ckSize = sizeof(Chunk) + SndDChunk.ckSize + sizeof(ChunkHeader) +
  264.               CommChunk.ckSize;
  265.  
  266.    if( fseek( file_ptr, 0, SEEK_SET ) != 0 ) return -1;
  267.  
  268.    if( fwrite( &FormChunk, sizeof(Chunk), 1, file_ptr ) != 1 ) return -1;
  269.  
  270.    if( fwrite( &CommChunk, sizeof(CommChunk), 1, file_ptr) != 1 ) return -1;
  271.  
  272.    if( fwrite( &SndDChunk, sizeof(SoundDataChunk), 1, file_ptr) != 1 ) return -1;
  273.  
  274.    return 0;
  275. }
  276.  
  277.  
  278.